#include "RenderableReader.h"
#include "sqplus/sqplus.h"
#include "../ScriptManager.h"
#include "../core/Rect2D.h"

using namespace SqPlus;


const std::string RenderableReader::_NAME_TAG				= "name";
const std::string RenderableReader::_CENTERTYPE_TAG			= "CenterType";
const std::string RenderableReader::_FLIPTYPE_TAG			= "FlipType";
const std::string RenderableReader::_COLLIDETYPE_TAG		= "CollideType";
const std::string RenderableReader::_BLENDTYPE_TAG			= "BlendType";
const std::string RenderableReader::_BLENDCOLOR_TAG			= "BlendColor";
const std::string RenderableReader::_LOCKED_TAG				= "Locked";
const std::string RenderableReader::_VISIBLE_RECT_TAG		= "VisibleRect";
const std::string RenderableReader::_VISIBLE_CENTER_TAG		= "VisibleCenter";
const std::string RenderableReader::_VISIBLE_TAG			= "Visible";
const std::string RenderableReader::_SORT_TAG				= "Sort";
const std::string RenderableReader::_ORIGIN_TAG				= "Origin";
const std::string RenderableReader::_UP_TAG					= "Up";

const std::string RenderableReader::_CENTER_LT_TAG			= "CENTER_LT";
const std::string RenderableReader::_CENTER_CT_TAG			= "CENTER_CT";
const std::string RenderableReader::_CENTER_RT_TAG			= "CENTER_RT";
const std::string RenderableReader::_CENTER_LM_TAG			= "CENTER_LM";
const std::string RenderableReader::_CENTER_CM_TAG			= "CENTER_CM";
const std::string RenderableReader::_CENTER_RM_TAG			= "CENTER_RM";
const std::string RenderableReader::_CENTER_LB_TAG			= "CENTER_LB";
const std::string RenderableReader::_CENTER_CB_TAG			= "CENTER_CB";
const std::string RenderableReader::_CENTER_RB_TAG			= "CENTER_RB";

const std::string RenderableReader::_FLIP_NONE_TAG			= "FLIP_NONE";
const std::string RenderableReader::_FLIP_LEFTRIGHT_TAG		= "FLIP_LEFTRIGHT";
const std::string RenderableReader::_FLIP_TOPBOTTOM_TAG		= "FLIP_TOPBOTTOM";

const std::string RenderableReader::_COLLIDABLE_PIXEL_TAG	= "COLLIDABLE_PIXEL";
const std::string RenderableReader::_COLLIDABLE_LINE_TAG	= "COLLIDABLE_LINE";
const std::string RenderableReader::_COLLIDABLE_TRIANGLE_TAG="COLLIDABLE_TRIANGLE";
const std::string RenderableReader::_COLLIDABLE_RECT_TAG	= "COLLIDABLE_RECT";
const std::string RenderableReader::_COLLIDABLE_POLYGON_TAG	= "COLLIDABLE_POLYGON";

const std::string RenderableReader::_BLEND_NONE_TAG			= "BLEND_NONE";
const std::string RenderableReader::_BLEND_ALPHA_TAG		= "BLEND_ALPHA";
const std::string RenderableReader::_BLEND_ADD_TAG			= "BLEND_ADD";
const std::string RenderableReader::_BLEND_SUB_TAG			= "BLEND_SUB";
const std::string RenderableReader::_BLEND_DARKEN_TAG		= "BLEND_DARKEN";
const std::string RenderableReader::_BLEND_LIGHTEN_TAG		= "BLEND_LIGHTEN";
const std::string RenderableReader::_BLEND_MULTIPLY_TAG		= "BLEND_MULTIPLY";
const std::string RenderableReader::_BLEND_SCREEN_TAG		= "BLEND_SCREEN";
const std::string RenderableReader::_BLEND_DIFFERENCE_TAG	= "BLEND_DIFFERENCE";
const std::string RenderableReader::_BLEND_INVERSE_DIFFERENCE_TAG	= "BLEND_INVERSE_DIFFERENCE";
const std::string RenderableReader::_BLEND_INVERT_TAG		= "BLEND_INVERT";
const std::string RenderableReader::_BLEND_DODGE_TAG		= "BLEND_DODGE";

const std::string RenderableReader::_TRUE_TAG				= "true";
const std::string RenderableReader::_FALSE_TAG				= "false";

const std::string RenderableReader::_POSITION_TAG			= "Position";
const std::string RenderableReader::_X_TAG					= "x";
const std::string RenderableReader::_Y_TAG					= "y";

const std::string RenderableReader::_SCRIPT_FILE_TAG		= "ScriptFile";
const std::string RenderableReader::_ON_LOAD_TAG			= "onLoad";


void RenderableReader::parseRenderable(TiXmlElement* element, Renderable* renderable)
{
	//read renderable tag
	char* sName = (char*)element->Attribute(_NAME_TAG.c_str());
	char* sCenterType = (char*)element->Attribute(_CENTERTYPE_TAG.c_str());
	char* sFlipType = (char*)element->Attribute(_FLIPTYPE_TAG.c_str());
	char* sCollideType = (char*)element->Attribute(_COLLIDETYPE_TAG.c_str());
	char* sBlendColor = (char*)element->Attribute(_BLENDCOLOR_TAG.c_str());
	char* sLocked = (char*)element->Attribute(_LOCKED_TAG.c_str());
	char* sVisibleRect = (char*)element->Attribute(_VISIBLE_RECT_TAG.c_str());
	char* sVisibleCenter = (char*)element->Attribute(_VISIBLE_CENTER_TAG.c_str());
	char* sVisible = (char*)element->Attribute(_VISIBLE_TAG.c_str());
	char* sBlendType = (char*)element->Attribute(_BLENDTYPE_TAG.c_str());
	char* sSort = (char*)element->Attribute(_SORT_TAG.c_str());

	TiXmlElement* node = element->FirstChildElement(_NAME_TAG.c_str()); if(node) sName = (char*)node->GetText();
	node = element->FirstChildElement(_CENTERTYPE_TAG.c_str()); if(node) sCenterType = (char*)node->GetText();
	node = element->FirstChildElement(_FLIPTYPE_TAG.c_str()); if(node) sFlipType = (char*)node->GetText();
	node = element->FirstChildElement(_COLLIDETYPE_TAG.c_str()); if(node) sCollideType = (char*)node->GetText();
	node = element->FirstChildElement(_BLENDCOLOR_TAG.c_str()); if(node) sBlendColor = (char*)node->GetText();
	node = element->FirstChildElement(_LOCKED_TAG.c_str()); if(node) sLocked = (char*)node->GetText();
	node = element->FirstChildElement(_VISIBLE_RECT_TAG.c_str()); if(node) sVisibleRect = (char*)node->GetText();
	node = element->FirstChildElement(_VISIBLE_CENTER_TAG.c_str()); if(node) sVisibleCenter = (char*)node->GetText();
	node = element->FirstChildElement(_VISIBLE_TAG.c_str()); if(node) sVisible = (char*)node->GetText();
	node = element->FirstChildElement(_BLENDTYPE_TAG.c_str()); if(node) sBlendType = (char*)node->GetText();
	node = element->FirstChildElement(_SORT_TAG.c_str()); if(node) sSort = (char*)node->GetText();

	TCHAR wstr[512]; memset(wstr, 0, sizeof(wstr));
	if(sName)
#ifdef UNICODE
	{
		::MultiByteToWideChar(CP_UTF8, 0, sName, (int32)strlen(sName), wstr, 512);
		renderable->setName(wstr);
	}
#else
		renderable->setName(sName);
#endif

	if(sCenterType)
	{
		if(sCenterType == _CENTER_LT_TAG)
			renderable->setCenterType(Rect2D::CENTER_LT);
		else if(sCenterType == _CENTER_CT_TAG)
			renderable->setCenterType(Rect2D::CENTER_CT);
		else if(sCenterType == _CENTER_RT_TAG)
			renderable->setCenterType(Rect2D::CENTER_RT);
		else if(sCenterType == _CENTER_LM_TAG)
			renderable->setCenterType(Rect2D::CENTER_LM);
		else if(sCenterType == _CENTER_CM_TAG)
			renderable->setCenterType(Rect2D::CENTER_CM);
		else if(sCenterType == _CENTER_RM_TAG)
			renderable->setCenterType(Rect2D::CENTER_RM);
		else if(sCenterType == _CENTER_LB_TAG)
			renderable->setCenterType(Rect2D::CENTER_LB);
		else if(sCenterType == _CENTER_CB_TAG)
			renderable->setCenterType(Rect2D::CENTER_CB);
		else if(sCenterType == _CENTER_RB_TAG)
			renderable->setCenterType(Rect2D::CENTER_RB);
	}

	if(sFlipType)
	{
		if(sFlipType == _FLIP_NONE_TAG)
			renderable->setFlipType(Renderable::FLIP_NONE);
		else if(sFlipType == _FLIP_LEFTRIGHT_TAG)
			renderable->setFlipType(Renderable::FLIP_LEFT_RIGHT);
		else if(sFlipType == _FLIP_TOPBOTTOM_TAG)
			renderable->setFlipType(Renderable::FLIP_TOP_BOTTOM);
	}

	if(sCollideType)
	{
		if(sCollideType == _COLLIDABLE_PIXEL_TAG)
			renderable->setCollideType(Collidable::COLLIDABLE_PIXEL);
		else if(sCollideType == _COLLIDABLE_LINE_TAG)
			renderable->setCollideType(Collidable::COLLIDABLE_LINE);
		else if(sCollideType == _COLLIDABLE_TRIANGLE_TAG)
			renderable->setCollideType(Collidable::COLLIDABLE_TRIANGLE);
		else if(sCollideType == _COLLIDABLE_RECT_TAG)
			renderable->setCollideType(Collidable::COLLIDABLE_RECT);
		else if(sCollideType == _COLLIDABLE_POLYGON_TAG)
			renderable->setCollideType(Collidable::COLLIDABLE_POLYGON);
	}

	if(sBlendColor)
	{
		uint32 color32;
		Color color;

		sscanf(sBlendColor, "%x", &color32);
		color = Color::fromARGB((float)((color32>>24)&0xFF)/255.f, (float)((color32>>16)&0xFF)/255.f,
			(float)((color32>>8)&0xFF)/255.f, (float)((color32>>0)&0xFF)/255.f);
		renderable->setBlendColor(color);
	}

	if(sLocked)
	{
		if(sLocked == _TRUE_TAG)
			renderable->setLocked(true);
		else if(sLocked == _FALSE_TAG)
			renderable->setLocked(false);
	}

	if(sVisibleRect)
	{
		if(sVisibleRect == _TRUE_TAG)
			renderable->setVisibleRect(true);
		else if(sVisibleRect == _FALSE_TAG)
			renderable->setVisibleRect(false);
	}

	if(sVisibleCenter)
	{
		if(sVisibleCenter == _TRUE_TAG)
			renderable->setVisibleCenter(true);
		else if(sVisibleCenter == _FALSE_TAG)
			renderable->setVisibleCenter(false);
	}

	if(sVisible)
	{
		if(sVisible == _TRUE_TAG)
			renderable->setVisible(true);
		else if(sVisible == _FALSE_TAG)
			renderable->setVisible(false);
	}

	if(sSort)
	{
		if(sSort == _TRUE_TAG)
			renderable->setSort(true);
		else if(sSort == _FALSE_TAG)
			renderable->setSort(false);
	}

	if(sBlendType)
	{
		if(sBlendType == _BLEND_NONE_TAG)
			renderable->setBlendType(Color::BLEND_NONE);
		else if(sBlendType == _BLEND_ALPHA_TAG)
			renderable->setBlendType(Color::BLEND_ALPHA);
		else if(sBlendType == _BLEND_ADD_TAG)
			renderable->setBlendType(Color::BLEND_ADD);
		else if(sBlendType == _BLEND_SUB_TAG)
			renderable->setBlendType(Color::BLEND_SUB);
		else if(sBlendType == _BLEND_DARKEN_TAG)
			renderable->setBlendType(Color::BLEND_DARKEN);
		else if(sBlendType == _BLEND_LIGHTEN_TAG)
			renderable->setBlendType(Color::BLEND_LIGHTEN);
		else if(sBlendType == _BLEND_MULTIPLY_TAG)
			renderable->setBlendType(Color::BLEND_MULTIPLY);
		else if(sBlendType == _BLEND_SCREEN_TAG)
			renderable->setBlendType(Color::BLEND_SCREEN);
		else if(sBlendType == _BLEND_DIFFERENCE_TAG)
			renderable->setBlendType(Color::BLEND_DIFFERENCE);
		else if(sBlendType == _BLEND_INVERSE_DIFFERENCE_TAG)
			renderable->setBlendType(Color::BLEND_INVERSE_DIFFERENCE);
		else if(sBlendType == _BLEND_INVERT_TAG)
			renderable->setBlendType(Color::BLEND_INVERT);
		else if(sBlendType == _BLEND_DODGE_TAG)
			renderable->setBlendType(Color::BLEND_DODGE);
	}

	TiXmlElement* position = element->FirstChildElement(_POSITION_TAG.c_str());
	if(position)
	{
		int32 x = 0, y = 0;
		position->Attribute(_X_TAG.c_str(), &x);
		node = position->FirstChildElement(_X_TAG.c_str()); if(node) x = atoi(node->GetText());
		position->Attribute(_Y_TAG.c_str(), &y);
		node = position->FirstChildElement(_Y_TAG.c_str()); if(node) y = atoi(node->GetText());

		renderable->setPosition(Vector2D((float)x, (float)y));
	}

	TiXmlElement* origin = element->FirstChildElement(_ORIGIN_TAG.c_str());
	if(origin)
	{
		int32 x = 0, y = 0;
		origin->Attribute(_X_TAG.c_str(), &x);
		node = origin->FirstChildElement(_X_TAG.c_str()); if(node) x = atoi(node->GetText());
		origin->Attribute(_Y_TAG.c_str(), &y);
		node = origin->FirstChildElement(_Y_TAG.c_str()); if(node) y = atoi(node->GetText());

		renderable->setOrigin(Vector2D((float)x, (float)y));
	}

	TiXmlElement* up = element->FirstChildElement(_UP_TAG.c_str());
	if(up)
	{
		int32 x = 0, y = 0;
		up->Attribute(_X_TAG.c_str(), &x);
		node = up->FirstChildElement(_X_TAG.c_str()); if(node) x = atoi(node->GetText());
		up->Attribute(_Y_TAG.c_str(), &y);
		node = up->FirstChildElement(_Y_TAG.c_str()); if(node) y = atoi(node->GetText());

		renderable->setUp(Vector2D((float)x, (float)y));
	}
}

void RenderableReader::parseScript(TiXmlElement* element, Renderable* renderable)
{
	char* scriptFile = (char*)element->Attribute(_SCRIPT_FILE_TAG.c_str());
	TiXmlElement* node = element->FirstChildElement(_SCRIPT_FILE_TAG.c_str()); if(node) scriptFile = (char*)node->GetText();

	if(scriptFile)
	{
#ifdef UNICODE
		TCHAR wstr[512]; memset(wstr, 0, sizeof(wstr));
		::MultiByteToWideChar(CP_UTF8, 0, scriptFile, (int32)strlen(scriptFile), wstr, 512);
		ScriptManager::GetInstance().load(wstr);
#else
		ScriptManager::GetInstance().load(scriptFile);
#endif
	}

	char* onLoad = (char*)element->Attribute(_ON_LOAD_TAG.c_str());
	node = element->FirstChildElement(_ON_LOAD_TAG.c_str()); if(node) onLoad = (char*)node->GetText();

	if(onLoad)
	{
		//call script function
#ifdef UNICODE
		TCHAR wstr[512]; memset(wstr, 0, sizeof(wstr));
		::MultiByteToWideChar(CP_UTF8, 0, onLoad, (int32)strlen(onLoad), wstr, 512);
		SquirrelFunction<void>((const SQChar*)wstr)(renderable);
#else
		SquirrelFunction<void>((const SQChar*)onLoad)(renderable);
#endif
	}
}

void RenderableReader::parseAttachment(TiXmlElement* element, Renderable* renderable)
{
	char* sName = (char*)element->Attribute(_NAME_TAG.c_str());
	TiXmlElement* node = element->FirstChildElement(_NAME_TAG.c_str()); if(node) sName = (char*)node->GetText();

	TiXmlElement* position = element->FirstChildElement(_POSITION_TAG.c_str());
	if(position)
	{
		int32 x = 0, y = 0;

		position->Attribute(_X_TAG.c_str(), &x);
		node = position->FirstChildElement(_X_TAG.c_str()); if(node) x = atoi(node->GetText());
		position->Attribute(_Y_TAG.c_str(), &y);
		node = position->FirstChildElement(_Y_TAG.c_str()); if(node) y = atoi(node->GetText());

		if(sName)
#ifdef UNICODE
		{
			TCHAR wstr[512]; memset(wstr, 0, sizeof(wstr));
			::MultiByteToWideChar(CP_UTF8, 0, sName, (int32)strlen(sName), wstr, 512);
			renderable->addAttachment(wstr, Vector2D((float)x, (float)y));
		}
#else
			renderable->addAttachment(sName, Vector2D((float)x, (float)y));
#endif
		else
			renderable->addAttachment(_T(""), Vector2D((float)x, (float)y));
	}
}